package cn.lg.soar.general.api.utils;

import cn.lg.soar.general.api.model.BizFileDTO;
import cn.lg.soar.general.api.model.FileVO;
import cn.lg.soar.general.api.service.IFileApi;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author luguoxiang 469599794@qq.com
 * @Date: 2024/6/3 20:41
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface BizFileBuilder {

    /**
     * 构建附件写入器（保存附件）
     * @param bizId 业务id
     * @return
     */
    static Writer writer(long bizId) {
        return new Writer(bizId);
    }

    /**
     * 构建附件读取器（获取附件）
     * @param bizId 业务id
     * @return
     */
    static Reader reader(long bizId) {
        return new Reader(bizId);
    }

    class Writer {

        private final long bizId;
        private final List<BizFileDTO> list;

        /**
         * @param bizId 业务id
         */
        public Writer(long bizId) {
            this.bizId = bizId;
            list = new ArrayList<>();
        }

        /**
         * 增加类型-字段映射
         * @param bizType 业务类型
         * @param supplier 提供附件（vo的get方法）
         * @return
         */
        public Writer mapper(String bizType, Supplier<List<FileVO>> supplier) {
            list.add(new BizFileDTO(bizType, supplier.get()));
            return this;
        }

        /**
         * 增加类型-字段映射
         * @param bizType 业务类型
         * @param supplier 提供附件（vo的get方法）
         * @return
         */
        public Writer mapper(Enum<?> bizType, Supplier<List<FileVO>> supplier) {
            list.add(new BizFileDTO(bizType.name(), supplier.get()));
            return this;
        }

        /**
         * 执行写入
         * @param fileApi
         * @return
         */
        public boolean execute(IFileApi fileApi) {
            return fileApi.saveBizFile(bizId, list);
        }

        /**
         * 添加附件
         * @param bizType
         * @param fileVos
         * @return
         */
        public Writer add(String bizType, List<FileVO> fileVos) {
            list.add(new BizFileDTO(bizType, fileVos));
            return this;
        }

        /**
         * 添加附件
         * @param bizType
         * @param fileVos
         * @return
         */
        public Writer add(Enum<?> bizType, List<FileVO> fileVos) {
            list.add(new BizFileDTO(bizType.name(), fileVos));
            return this;
        }

        public List<BizFileDTO> build() {
            return list;
        }
    }

    class Reader {

        private final long bizId;
        private final Map<String, Consumer<List<FileVO>>> map;

        /**
         * @param bizId 业务id
         */
        public Reader(long bizId) {
            this.bizId = bizId;
            map = new HashMap<>();
        }

        /**
         * 增加类型-字段映射
         * @param bizType 业务类型
         * @param consumer 消费附件（vo的set方法）
         * @return
         */
        public Reader mapper(String bizType, Consumer<List<FileVO>> consumer) {
            map.put(bizType, consumer);
            return this;
        }

        /**
         * 增加类型-字段映射
         * @param bizType 业务类型
         * @param consumer 消费附件（vo的set方法）
         * @return
         */
        public Reader mapper(Enum<?> bizType, Consumer<List<FileVO>> consumer) {
            map.put(bizType.name(), consumer);
            return this;
        }

        /**
         * 增加类型-字段映射
         * @param bizType 业务类型
         * @param consumer 消费附件（vo的set方法）
         * @return
         */
        public Reader mapper(String bizType, Function<List<FileVO>, ?> consumer) {
            map.put(bizType, consumer::apply);
            return this;
        }

        /**
         * 增加类型-字段映射
         * @param bizType 业务类型
         * @param consumer 消费附件（vo的set方法）
         * @return
         */
        public Reader mapper(Enum<?> bizType, Function<List<FileVO>, ?> consumer) {
            map.put(bizType.name(), consumer::apply);
            return this;
        }

        /**
         * 执行读取
         * @param fileApi
         */
        public void execute(IFileApi fileApi) {
            Map<String, List<FileVO>> fileMap = fileApi.getBizFile(bizId, map.keySet());
            map.forEach((k, v) -> {
                v.accept(fileMap.get(k));
            });
        }

        public Set<String> build() {
            return map.keySet();
        }
    }

}
